fn main() {
    {
        print!("\t Start with a tab\nand move to a new line");
    }

    println!();

    {
        // Note: After the first line you have to start on the far left.
        // If you write directly under println!, it will add the spaces.
        println!(
            "Inside quotes
you can write over
many lines
and it will print just fine."
        );

        println!();

        println!(
            "If you forget to write
            on the left side, the spaces
            will be added when you print."
        );
    }

    println!();

    {
        // If you want to print characters like \n (called "escape characters"),
        // you can add an extra \.
        println!("Here are two escape characters: \\n and \\t");
    }

    println!();

    {
        // We used \ five times here.
        println!("He said, \"You can find the file at c:\\files\\my_documents\\file.txt.\" Then I found the file.");
        println!(
            r#"He said, "You can find the file at c:\files\my_documents\file.txt." Then I found the file."#
        )
    }

    println!();

    {
        // If you need to print with a # inside, then you can start with r## and
        // end with ##. And if you need more than one, you can add one more # on
        // each side.

        // Single quotes.
        let my_string = "'Ice to see you,' he said.";
        // Double quotes.
        let quote_string = r#""Ice to see you," he said."#;
        // Has one # so we need at least ##.
        let hashtag_string = r##"The hashtag #IceToSeeYou had become very popular."##;
        // Has three ### so we need at least ####.
        let many_hashtags =
            r####""You don't have to type ### to use a hashtag. You can just use #.""####;
        println!(
            "{}\n{}\n{}\n{}",
            my_string, quote_string, hashtag_string, many_hashtags
        );
    }

    println!();

    #[allow(unused_assignments)]
    {
        // r# has another use: with it you can use a keyword (words like let,
        // fn, etc.) as a variable name.
        //
        // r# has this function because older versions of Rust had fewer
        // keywords than Rust now. So with r# you can avoid mistakes with
        // variable names that were not keywords before.

        // The variable's name is let.
        let r#let = 6;
        // This variable's name is mut.
        let mut r#mut = 10;
        r#mut = 11;
        println!("{}\n{}\n", r#let, r#mut);

        // Or maybe for some reason you really need a function to have a name
        // like return. Then you can write this.
        fn r#return() -> u8 {
            println!("Here is your number.");

            8
        }

        let my_number = r#return();
        println!("{}", my_number);
    }

    println!();

    {
        // If you want to print the bytes of a &str or a char, you can just
        // write b before the string. This works for all ASCII characters. These
        // are all the ASCII characters:
        //
        // ☺☻♥♦♣♠♫☼►◄↕‼¶§▬↨↑↓→∟↔▲▼123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

        println!("{:?}", b"This will look like numbers");
        println!("{:#?}", b"This will look like numbers");
        println!("{:?}", br##"I like to write "#"."##);
        println!("{:#?}", br##"I like to write "#"."##);
    }

    println!();

    {
        // There is also a Unicode escape that lets you print any Unicode
        // character inside a string: \u{}. A hexadecimal number goes inside
        // the {} to print it.

        // Cast char as u32 to get the hexadecimal value.
        println!("{:X}", '행' as u32);
        println!("{:X}", 'H' as u32);
        println!("{:X}", '居' as u32);
        println!("{:X}", 'い' as u32);

        // Try printing them with Unicode escape \u.
        println!("\u{D589}, \u{48}, \u{5C45}, \u{3044}");
    }

    println!();

    {
        // We know that println! can print with {} (for Display) and {:?}
        // (for Debug), plus {:#?} for pretty printing. But there are many other
        // ways to print.
        //
        // For example, if you have a reference, you can use {:p} to print the
        // pointer address. Pointer address means the location in your
        // computer's memory.
        let number = 9;
        let number_ref = &number;
        println!("{:p}", number_ref);

        println!();

        // Or you can print binary, hexadecimal and octal.
        let number = 555;
        println!(
            "Binary: {:b}, hexadecimal: {:x}, octal: {:o}",
            number, number, number
        );
    }

    println!();

    {
        let father_name = "Vlad";
        let son_name = "Adrian Fahrenheit";
        let family_name = "Țepeș";
        println!(
            "This is {1} {2}, son of {0} {2}.",
            father_name, son_name, family_name
        );
    }

    println!();

    #[allow(clippy::print_literal)]
    {
        println!(
            "{city1} is in {country} and {city2} is also in {country}, \
            but {city3} is not in {country}.",
            city1 = "Seoul",
            city2 = "Busan",
            city3 = "Tokyo",
            country = "Korea"
        );
    }

    println!();

    {
        // Very complex printing is also possible in Rust if you want to use it.
        // Here is how to do it:
        //
        // {variable:padding alignment minimum.maximum}
        //
        // To understand this, look at the
        //
        // 1. Do you want a variable name? Write that first, like when we wrote
        //    {country} above. (Then add a : after it if you want to do more
        //    things).
        // 2. Do you want a padding character? For example, 55 with three
        //    "padding zeros" looks like 00055.
        // 3. What alignment (left/middle/right) for the padding?
        // 4. Do you want a minimum length? (Just write a number.)
        // 5. Do you want a maximum length? (Write a number with a . in front.)

        // For example, if I want to write "a" with five ㅎ characters on the
        // left and five ㅎ characters on the right:
        let letter = "a";
        println!("{:ㅎ^11}", letter);

        // This prints ㅎㅎㅎㅎㅎaㅎㅎㅎㅎㅎ. Let's look at 1) to 5) for this to
        // understand how the compiler reads it.
        //
        // 1. Do you want a variable name? {:ㅎ^11} There is no variable name.
        //    There is nothing before :.
        // 2. Do you want a padding character? {:ㅎ^11} Yes. ㅎ comes after the
        //    : and has a ^. < means padding with the character on the left,
        //    > means on the right, and ^ means in the middle.
        // 3. Do you want a minimum length? {:ㅎ^11} Yes: there is an 11 after.
        // 4. Do you want a maximum length? {:ㅎ^11} No: there is no number with
        //    a . before.
    }

    println!();

    {
        // Here is an example of many types of formatting.
        let title = "TODAY'S NEWS";
        // No variable name, pad with -, put in centre, 30 characters long.
        println!("{:-^30}", title);
        let bar = "|";
        // No variable name, pad with space, 15 characters each, one to the
        // left, one to the right.
        println!("{: <15}{: >15}", bar, bar);
        let a = "SEOUL";
        let b = "TOKYO";
        // Variable names city1 and city2, pad with -, one to the left, one to
        // the right.
        println!("{city1:-<15}{city2:->15}", city1 = a, city2 = b);
    }
}
